package main
import (
	"fmt"
	//"unsafe"
)

/*
单链表
https://www.cnblogs.com/skzxc/p/11453679.html
*/ 

type Node struct {
	Data	interface{}
	Next	*Node
}

type Link struct{
	Head 	*Node
	Length 	int
}

//设计接口
type Method interface {
	Insert(i int,v interface{})
	Delete(i int)
	GetLength() int
	Search(v interface{}) int
	IsNil() bool
}


func CreateNode(v interface{}) *Node {
	node := &Node{v,nil}
	return node
}

func CreateLink() *Link {
	return &Link{CreateNode(nil),0}
}


func (list *Link) Insert(i int,v interface{})  {
	if i == 0 || list.Length < i - 1 {
		i = list.Length + 1
	}

	node := CreateNode(v)
	pre := list.Head
	for index := 1; index <= i; index++ {
		if index == i {
			node.Next = pre.Next
			pre.Next = node
			list.Length++
		}
		pre = pre.Next
	}
}

func (list *Link) Delete(i int)  {
	if list.Length < i {
		return
	}
	pre := list.Head
	for index := 0; index <= i; index++ {
		node := pre.Next
		if index == i-1 {
			pre.Next = node.Next
			list.Length--
		}
		if pre.Next == nil {
			return
		}
		pre = pre.Next
	}
}

func (list *Link) GetLength() int {
	return list.Length
}

func (list *Link) Search(v interface{}) int {
	pre := list.Head.Next
	for i := 1; i <= list.Length; i++ {
		if pre.Data == v {
			return i
		}
		pre = pre.Next
	}
	return 0
}

func (list *Link) IsNil() bool {
	pre := list.Head.Next
	if pre == nil {
		return true
	}
	return false
}


// main 函数：
func main() {
    lList := CreateLink()
    fmt.Println("List is null: ", lList.IsNil())
    var M Method
	M = lList       // 接口类型的变量可以存储所有实现该接口的类型变量 
	M.Insert(1, 3)
    M.Insert(2, 6)
    M.Insert(3, 5)
	M.Insert(21, 8)
	
    M.Delete(3)
	M.Insert(3, 15)
	M.Insert(1, 2)
	M.Insert(1, 1)
	M.Insert(0, 100)
	M.Insert(0, 101)

    PrintList(lList)
    fmt.Println("List length is: ", lList.Length)
    fmt.Println("元素6在位置：", M.Search(6))
    fmt.Println("元素100在位置：", M.Search(100))
    fmt.Println("List is null: ", lList.IsNil())
 
    M.Delete(2)
    M.Delete(22)
	M.Delete(1)
	M.Delete(1)
	M.Delete(2)
	M.Delete(1)
	M.Delete(1)
    PrintList(lList)
	fmt.Println("List length is: ", lList.Length)
}

func PrintList(list *Link)  {
	fmt.Println("lList shows as follows: ...")
	pre := list.Head.Next
	for i := 1; i <= list.Length; i++ {
		fmt.Printf("Data:%v  Index:%v\n",pre.Data,i)
		pre = pre.Next
	}
}
